package com.dx.zkClient;

import java.util.Map;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.imps.CuratorFrameworkState;
import org.apache.curator.retry.ExponentialBackoffRetry;

import com.dx.zkClient.cfg.ConfigConstants;
import com.dx.zkClient.cfg.ZkConfigManager;

/**
* @ClassName: ZKClient 
* @Description: zookeeper客户端 
* @author wuzhenfang(wzfbj2008@163.com)
* @date 2016年4月12日 下午3:24:06 
* @version V1.0
 */
public class ZKClient {

	private static String connectString = "localhost:2181";//zookeeper服务器列表，如：host1:port,host2:port
	
	private static int sessionTimeoutMs = 5000;//会话超时时间，默认是60000ms

	private static int connectionTimeoutMs = 30000;//连接创建烧蚀时间，单位毫秒，默认是15000ms
	
	private static boolean canBeReadOnly =  true;//只读，不能改数据
	
	private static int baseSleepTimeMs = 1000;//初始睡眠sleep时间
	
	private static String namespace = "/dxDemo";//默认命名空间，每个应用都应该配置各自的命名空间
	
	private static CuratorFramework client;
	
	private ZKClient(){};
	
	/**
	 * 单例获取客户端实例
	 * @return
	 */
	public static CuratorFramework getInstance() {
		if (client == null) {
			synchronized (client) {
				if (client == null) {
					client = newClient(loadZKConfig());
					client.start();
				}
			}
		} else {
			if (client.getState().compareTo(CuratorFrameworkState.STARTED) != 0) {
				client.start();
			}
		}
		return client;
	}
	
	/**
	 * 单例创建客户端
	 * @param configMap 配置
	 * @return
	 */
	private static CuratorFramework newClient(Map<String,String> configMap){
		CuratorFramework client = CuratorFrameworkFactory
				.builder()
				.connectString((configMap.get(ConfigConstants.CONNECTSTRING) != null)? configMap.get(ConfigConstants.CONNECTSTRING):connectString)
				.sessionTimeoutMs((configMap.get(ConfigConstants.SESSIONTIMEOUTMS) != null)? Integer.valueOf(configMap.get(ConfigConstants.SESSIONTIMEOUTMS)):sessionTimeoutMs)
				.connectionTimeoutMs((configMap.get(ConfigConstants.CONNECTIONTIMEOUTMS) != null)? Integer.valueOf(configMap.get(ConfigConstants.CONNECTIONTIMEOUTMS)):connectionTimeoutMs)
				.canBeReadOnly((configMap.get(ConfigConstants.CANBEREADONLY) != null)? Boolean.valueOf(configMap.get(ConfigConstants.CANBEREADONLY)):canBeReadOnly)
				.retryPolicy(new ExponentialBackoffRetry((configMap.get(ConfigConstants.BASESLEEPTIMEMS) != null)? Integer.valueOf(configMap.get(ConfigConstants.BASESLEEPTIMEMS)):baseSleepTimeMs, Integer.MAX_VALUE))
				.namespace((configMap.get(ConfigConstants.NAMESPACE) != null)? configMap.get(ConfigConstants.NAMESPACE):namespace)
				.build();
		return client;		
	}
	
	/**
	 * 从zk配置管理器中加载配置信息
	 * @return
	 */
	private static Map<String,String> loadZKConfig(){
		return ZkConfigManager.getProperties();
	}
	
	/**
	 * 关闭客户端
	 */
	public static void close(){
		client.close();
	}
}
